home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / news / inn1.000 / inn1.4sec-linux-src.tar / inn / nnrpd / commands.c < prev    next >
C/C++ Source or Header  |  1993-03-18  |  10KB  |  448 lines

  1. /*  $Revision: 1.14 $
  2. **
  3. **  Miscellaneous commands.
  4. */
  5. #include "nnrpd.h"
  6. #include <time.h>
  7.  
  8.  
  9. typedef struct _LISTINFO {
  10.     STRING    File;
  11.     STRING    Items;
  12.     STRING    Format;
  13. } LISTINFO;
  14.  
  15.  
  16. STATIC LISTINFO        INFOactive = {
  17.     ACTIVE, "active newsgroups",
  18.     "Newsgroups in form \"group high low flags\""
  19. };
  20. STATIC LISTINFO        INFOactivetimes = {
  21.     ACTIVETIMES, "creation times",
  22.     "Group creations in form \"name time who\""
  23. };
  24. STATIC LISTINFO        INFOdistribs = {
  25.     _PATH_NNRPDIST, "newsgroup distributions",
  26.     "Distributions in form \"area description\""
  27. };
  28. STATIC LISTINFO        INFOdistribpats = {
  29.     _PATH_DISTPATS, "distribution patterns",
  30.     "Default distributions in form \"weight:pattern:value\""
  31. };
  32. STATIC LISTINFO        INFOgroups = {
  33.     NEWSGROUPS, "newsgroup descriptions",
  34.     "Descriptions in form \"group description\""
  35. };
  36. STATIC LISTINFO        INFOschema = {
  37.     _PATH_SCHEMA, "overview schema",
  38.     "Order of fields in overview database"
  39. };
  40.  
  41.  
  42. /* ARGSUSED */
  43. FUNCTYPE
  44. CMDauthinfo(ac, av)
  45.     int        ac;
  46.     char    *av[];
  47. {
  48.     static char    User[30];
  49.     static char    Password[30];
  50.     char    accesslist[BIG_BUFFER];
  51.  
  52.     if (caseEQ(av[1], "user")) {
  53.     (void)strncpy(User, av[2], sizeof User - 1);
  54.     User[sizeof User - 1] = 0;
  55.     Reply("%d PASS required\r\n", NNTP_AUTH_NEXT_VAL);
  56.     return;
  57.     }
  58.  
  59.     if (!caseEQ(av[1], "pass")) {
  60.     Reply("%d bad authinfo param\r\n", NNTP_BAD_COMMAND_VAL);
  61.     return;
  62.     }
  63.     if (User[0] == '\0') {
  64.     Reply("%d USER required\r\n", NNTP_AUTH_REJECT_VAL);
  65.     return;
  66.     }
  67.  
  68.     (void)strncpy(Password, av[2], sizeof Password - 1);
  69.     Password[sizeof Password - 1] = 0;
  70.  
  71.     if (EQ(User, PERMuser) && EQ(Password, PERMpass)) {
  72.     syslog(L_NOTICE, "%s user %s", ClientHost, User);
  73.     Reply("%d Ok\r\n", NNTP_AUTH_OK_VAL);
  74.     PERMneedauth = FALSE;
  75.     PERMauthorized = TRUE;
  76.     return;
  77.     }
  78.     if (PERMinfile((char *)NULL, (char *)NULL, User, Password, accesslist)) {
  79.     PERMspecified = NGgetlist(&PERMlist, accesslist);
  80.     syslog(L_NOTICE, "%s user %s", ClientHost, User);
  81.     Reply("%d Ok\r\n", NNTP_AUTH_OK_VAL);
  82.     PERMneedauth = FALSE;
  83.     PERMauthorized = TRUE;
  84.     return;
  85.     }
  86.  
  87.     syslog(L_FATAL, "%s bad_auth", ClientHost);
  88.     Reply("%d Authentication error\r\n", NNTP_ACCESS_VAL);
  89.     ExitWithStats(1);
  90. }
  91.  
  92.  
  93. /*
  94. **  The "DATE" command.  Part of NNTPv2.
  95. */
  96. /* ARGSUSED0 */
  97. FUNCTYPE
  98. CMDdate(ac, av)
  99.     int        ac;
  100.     char    *av[];
  101. {
  102.     TIMEINFO    t;
  103.     struct tm    *gmt;
  104.  
  105.     if (GetTimeInfo(&t) < 0 || (gmt = gmtime(&t.time)) == NULL) {
  106.     Reply("%d Can't get time, %s\r\n", NNTP_TEMPERR_VAL, strerror(errno));
  107.     return;
  108.     }
  109.     Reply("%d %04.4d%02.2d%02.2d%02.2d%02.2d%02.2d\r\n",
  110.     NNTP_DATE_FOLLOWS_VAL,
  111.     gmt->tm_year + 1900, gmt->tm_mon + 1, gmt->tm_mday,
  112.     gmt->tm_hour, gmt->tm_min, gmt->tm_sec);
  113. }
  114.  
  115.  
  116. /*
  117. **  List active newsgroups, newsgroup descriptions, and distributions.
  118. */
  119. /* ARGSUSED0 */
  120. FUNCTYPE
  121. CMDlist(ac, av)
  122.     int            ac;
  123.     char        *av[];
  124. {
  125.     register QIOSTATE    *qp;
  126.     register char    *p;
  127.     register char    *save;
  128.     char        *grplist[2];
  129.     LISTINFO        *lp;
  130.  
  131.     p = av[1];
  132.     if (p == NULL || caseEQ(p, "active")) {
  133.     if (!GetGroupList()) {
  134.         syslog(L_NOTICE, "%s cant getgroupslist for list %m", ClientHost);
  135.         Reply("%d Group update failed. Try later.\r\n", NNTP_TEMPERR_VAL);
  136.         ExitWithStats(1);
  137.     }
  138.     lp = &INFOactive;
  139.     }
  140.     else if (caseEQ(p, "active.times"))
  141.     lp = &INFOactivetimes;
  142.     else if (caseEQ(p, "distributions"))
  143.     lp = &INFOdistribs;
  144.     else if (caseEQ(p, "distrib.pats"))
  145.     lp = &INFOdistribpats;
  146.     else if (caseEQ(p, "newsgroups"))
  147.     lp = &INFOgroups;
  148.     else if (caseEQ(p, "overview.fmt"))
  149.     lp = &INFOschema;
  150.     else {
  151.     Reply("%s\r\n", NNTP_SYNTAX_USE);
  152.     return;
  153.     }
  154.  
  155.     if ((qp = QIOopen(lp->File, QIO_BUFFER)) == NULL) {
  156.     syslog(L_ERROR, "%s cant fopen %s %m", ClientHost, lp->File);
  157.     Reply("%d No list of %s available.\r\n", NNTP_TEMPERR_VAL, lp->Items);
  158.     return;
  159.     }
  160.  
  161.     Reply("%d %s.\r\n", NNTP_LIST_FOLLOWS_VAL, lp->Format);
  162.     if (!PERMspecified && !PERMdefault) {
  163.     /* Optmize for unlikely case of no permissions and FALSE default. */
  164.     (void)QIOclose(qp);
  165.     Printf(".\r\n");
  166.     }
  167.  
  168.     /* Set up group list terminator. */
  169.     grplist[1] = NULL;
  170.  
  171.     /* Read lines, ignore long ones. */
  172.     while ((p = QIOread(qp)) != NULL) {
  173.     if (lp == &INFOdistribs || lp == &INFOdistribpats) {
  174.         Printf("%s\r\n", p);
  175.         continue;
  176.     }
  177.     if (lp == &INFOschema) {
  178.         if (*p != '\0' && *p != '#')
  179.         Printf("%s\r\n", p);
  180.         continue;
  181.     }
  182.     if ((save = strchr(p, ' ')) != NULL)
  183.         *save = '\0';
  184.     if (PERMspecified) {
  185.         grplist[0] = p;
  186.         if (!PERMmatch(PERMdefault, PERMlist, grplist))
  187.         continue;
  188.     }
  189.     if (save != NULL)
  190.         *save = ' ';
  191.     Printf("%s\r\n", p);
  192.     }
  193.     QIOclose(qp);
  194.  
  195.     Printf(".\r\n");
  196. }
  197.  
  198.  
  199. /*
  200. **  Handle the "mode" command.
  201. */
  202. /* ARGSUSED */
  203. FUNCTYPE
  204. CMDmode(ac, av)
  205.     int        ac;
  206.     char    *av[];
  207. {
  208.     if (caseEQ(av[1], "reader"))
  209.     Reply("%d %s InterNetNews NNRP server %s ready (%s).\r\n",
  210.            PERMcanpost ? NNTP_POSTOK_VAL : NNTP_NOPOSTOK_VAL,
  211.            MyHostName, INNVersion(),
  212.            PERMcanpost ? "posting ok" : "no posting");
  213.     else
  214.     Reply("%d What?\r\n", NNTP_BAD_COMMAND_VAL);
  215. }
  216.  
  217.  
  218. /*
  219. **  Display new newsgroups since a given date and time for specified
  220. **  <distributions>.
  221. */
  222. FUNCTYPE
  223. CMDnewgroups(ac, av)
  224.     int            ac;
  225.     char        *av[];
  226. {
  227.     static char        USAGE[] =
  228.     "NEWGROUPS yymmdd hhmmss [\"GMT\"] [<distributions>]";
  229.     static char        **distlist;
  230.     register char    *p;
  231.     register char    *q;
  232.     register char    **dp;
  233.     register QIOSTATE    *qp;
  234.     register GROUPENTRY    *gp;
  235.     BOOL        All;
  236.     long        date;
  237.     char        *grplist[2];
  238.  
  239.     /* Parse the date. */
  240.     date = NNTPtoGMT(av[1], av[2]);
  241.     if (date < 0) {
  242.     Reply("%d Usage: %s\r\n", NNTP_SYNTAX_VAL, USAGE);
  243.     return;
  244.     }
  245.     ac -= 3;
  246.     av += 3;
  247.     if (ac > 0 && caseEQ(*av, "GMT")) {
  248.     av++;
  249.     ac--;
  250.     }
  251.     else
  252.     date = LOCALtoGMT(date);
  253.  
  254.     if (ac == 0)
  255.     All = TRUE;
  256.     else {
  257.     if (!ParseDistlist(&distlist, *av) < 0) {
  258.         Reply("%d Bad distribution list %s:\r\n", NNTP_SYNTAX_VAL, *av);
  259.         return;
  260.     }
  261.     All = FALSE;
  262.     }
  263.  
  264.     if (!GetGroupList()) {
  265.     syslog(L_NOTICE, "%s cant getgroupslist for list %m", ClientHost);
  266.     Reply("%d Group update failed. Try later.\r\n", NNTP_TEMPERR_VAL);
  267.     ExitWithStats(1);
  268.     }
  269.  
  270.     if ((qp = QIOopen(ACTIVETIMES, QIO_BUFFER)) == NULL) {
  271.     syslog(L_ERROR, "%s cant fopen %s %m",
  272.         ClientHost, ACTIVETIMES);
  273.     Reply("%d Cannot open newsgroup date file.\r\n", NNTP_TEMPERR_VAL);
  274.     return;
  275.     }
  276.     Reply("%d New newsgroups follow.\r\n", NNTP_NEWGROUPS_FOLLOWS_VAL);
  277.  
  278.     /* Read the file, ignoring long lines. */
  279.     while ((p = QIOread(qp)) != NULL) {
  280.     if ((q = strchr(p, ' ')) == NULL)
  281.         continue;
  282.     *q++ = '\0';
  283.     if (atol(q) < date || (gp = GRPfind(p)) == NULL)
  284.         continue;
  285.  
  286.     if (PERMspecified) {
  287.         grplist[0] = p;
  288.         grplist[1] = NULL;
  289.         if (!PERMmatch(PERMdefault, PERMlist, grplist))
  290.         continue;
  291.     }
  292.     else if (!PERMdefault)
  293.         continue;
  294.  
  295.     if (!All) {
  296.         if ((q = strchr(p, '.')) == NULL)
  297.         continue;
  298.         for (*q = '\0', dp = distlist; *dp; dp++)
  299.         if (EQ(p, *dp)) {
  300.             *q = '.';
  301.             break;
  302.         }
  303.         if (*dp == NULL)
  304.         continue;
  305.     }
  306.     Printf("%s %ld %ld %c%s\r\n",
  307.         p, (long)gp->High, (long)gp->Low,
  308.         gp->Flag, gp->Alias ? gp->Alias : "");
  309.     }
  310.     QIOclose(qp);
  311.     Printf(".\r\n");
  312. }
  313.  
  314.  
  315. /*
  316. **  Post an article.
  317. */
  318. /* ARGSUSED */
  319. FUNCTYPE
  320. CMDpost(ac, av)
  321.     int        ac;
  322.     char    *av[];
  323. {
  324.     static char        *article;
  325.     static int        size;
  326.     register char    *p;
  327.     register char    *end;
  328.     register int    longline;
  329.     register READTYPE    r;
  330.     int            i;
  331.     long        l;
  332.     STRING        response;
  333.     char        idbuff[SMBUF];
  334.  
  335.     if (!PERMcanpost) {
  336.     syslog(L_NOTICE, "%s noperm post without permission", ClientHost);
  337.     Reply("%s\r\n", NNTP_CANTPOST);
  338.     return;
  339.     }
  340.  
  341.     /* Start at beginning of buffer. */
  342.     if (article == NULL) {
  343.     size = 4096;
  344.     article = NEW(char, size);
  345.     }
  346.     p = article;
  347.     end = &article[size];
  348.  
  349.     Reply("%d Ok\r\n", NNTP_START_POST_VAL);
  350.     (void)fflush(stdout);
  351.  
  352.     for (l = 0, longline = 0; ; l++) {
  353.     /* Need more room? */
  354.     if (end - p < ART_LINE_MALLOC) {
  355.         i = p - article;
  356.         size += ART_LINE_MALLOC;
  357.         RENEW(article, char, size);
  358.         end = &article[size];
  359.         p = i + article;
  360.     }
  361.  
  362.     /* Read line, process bad cases. */
  363.     switch (r = READline(p, ART_LINE_LENGTH, DEFAULT_TIMEOUT)) {
  364.     default:
  365.         syslog(L_ERROR, "%s internal %d in post", ClientHost, r);
  366.         /* FALLTHROUGH */
  367.     case RTtimeout:
  368.         syslog(L_ERROR, "%s timeout in post", ClientHost);
  369.         Printf("%d timeout after %d seconds, closing connection\r\n",
  370.            NNTP_TEMPERR_VAL, DEFAULT_TIMEOUT);
  371.         ExitWithStats(1);
  372.         /* NOTREACHED */
  373.     case RTeof:
  374.         syslog(L_ERROR, "%s eof in post", ClientHost);
  375.         ExitWithStats(1);
  376.         /* NOTREACHED */
  377.     case RTlong:
  378.         if (longline == 0)
  379.         longline = l + 1;
  380.         continue;
  381.     case RTok:
  382.         break;
  383.     }
  384.  
  385.     /* Process normal text. */
  386.     if (*p != '.') {
  387.         p += strlen(p);
  388.         *p++ = '\n';
  389.         *p = '\0';
  390.         continue;
  391.     }
  392.  
  393.     /* Got a leading period; see if it's the terminator. */
  394.     if (p[1] == '\0') {
  395.         *p = '\0';
  396.         break;
  397.     }
  398.  
  399.     /* "Arnold, please copy down over the period for me." */
  400.     while ((p[0] = p[1]) != '\0')
  401.         p++;
  402.     *p++ = '\n';
  403.     *p = '\0';
  404.     }
  405.  
  406.     if (longline) {
  407.     syslog(L_NOTICE, "%s toolong in post", ClientHost);
  408.     Printf("%d Line %d too long\r\n", NNTP_POSTFAIL_VAL, longline);
  409.     POSTrejected++;
  410.     return;
  411.     }
  412.  
  413.     /* Send the article to the server. */
  414.     response = ARTpost(article, idbuff);
  415.     if (response == NULL) {
  416.     syslog(L_NOTICE, "%s post ok %s", ClientHost, idbuff);
  417.     Reply("%s\r\n", NNTP_POSTEDOK);
  418.     POSTreceived++;
  419.     }
  420.     else {
  421.     if ((p = strchr(response, '\r')) != NULL)
  422.         *p = '\0';
  423.     if ((p = strchr(response, '\n')) != NULL)
  424.         *p = '\0';
  425.     syslog(L_NOTICE, "%s post failed %s", ClientHost, response);
  426.     Reply("%d %s\r\n", NNTP_POSTFAIL_VAL, response);
  427.     POSTrejected++;
  428.     }
  429. }
  430.  
  431.  
  432. /*
  433. **  The "xpath" command.  An uncommon extension.
  434. */
  435. /* ARGSUSED */
  436. FUNCTYPE
  437. CMDxpath(ac, av)
  438.     int        ac;
  439.     char    *av[];
  440. {
  441.     char    *p;
  442.  
  443.     if ((p = HISgetent(av[1], TRUE)) == NULL)
  444.     Reply("%d Don't have it\r\n", NNTP_DONTHAVEIT_VAL);
  445.     else
  446.     Reply("%d %s\r\n", NNTP_NOTHING_FOLLOWS_VAL, p);
  447. }
  448.